/*This file is prepared for Doxygen automatic documentation generation.*/
//! \file *********************************************************************
//!
//! \brief Main for USB application.
//!
//! - Compiler:           IAR EWAVR and GNU GCC for AVR
//! - Supported devices:  AT90USB162, AT90USB82
//!
//! \author               Atmel Corporation: http://www.atmel.com \n
//!                       Support and FAQ: http://support.atmel.no/
//!
//! ***************************************************************************
//!
//! @mainpage AT90USB162 USB device HID generic demonstration
//!
//! @section intro License
//! Use of this program is subject to Atmel's End User License Agreement.
//!
//! Please read file  \ref lic_page for copyright notice.
//!
//! @section install Description
//! This embedded application code illustrates how to implement a USB application
//! with the AT90USBxxx controller using the generic HID class implementation.
//!
//! A pc side applications allow to communicate with the embedded firmware (see \ref UsbHidGenericDemos).
//!
//! The sample code is delivered for STK526.
//!
//! @section src_code About the source code
//! This source code is usable with the following compilers:
//! - IAR Embedded Workbench (5.11A and higher)
//! - AVRGCC (WinAVR 20080411 and higher).
//!
//! Support for other compilers may required modifications or attention for:
//! - compiler.h file 
//! - special registers declaration file
//! - interrupt subroutines declarations
//!
//! @section arch Architecture
//! As illustrated in the figure bellow, the application entry point is located is the main.c file.
//! The main function first performs the initialization of a scheduler module and then runs it in an infinite loop.
//! The scheduler is a simple infinite loop calling all its tasks defined in the conf_scheduler.h file.
//! No real time schedule is performed, when a task ends, the scheduler calls the next task defined in
//! the configuration file (conf_scheduler.h).
//!
//! The sample usb application is based on two different tasks:
//! - The usb_task  (usb_task.c associated source file), is the task performing the USB low level
//! enumeration process in device mode.
//! Once this task has detected that the usb connection is fully operationnal, it updates different status flags
//! that can be check within the high level application tasks.
//! - The hid task performs the high level device application operation.
//! Once the device is fully enumerated (DEVICE SETUP_SET_CONFIGURATION request received), the task
//! checks for received data on its OUT endpoint and transmit  data on its IN endpoint.
//!
//! \image html arch_full.gif
//!
//! ***************************************************************************

/* Copyright (c) 2009 Atmel Corporation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an Atmel
 * AVR product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

//_____  I N C L U D E S ___________________________________________________

#include "config.h"
#include "wdt_drv.h"
#include "power_drv.h"
#include "usb_drv.h"
#include "start_boot.h"
#include "umece498.h"
#include "usb_device_task.h"
#include "keyboard_task.h"
#include "usb_standard_request.h"
#include "analog_comparator.h"
#include <util/delay.h>
#include "fixed_point.h"
#include <stdio.h>
#include <avr/eeprom.h>

//_____ M A C R O S ________________________________________________________

//_____ D E F I N I T I O N S ______________________________________________
//#define is_btn_middle() ((PINB&(1<<PINB0))? FALSE : TRUE)

int main(void) __attribute__((noreturn));
void print_int(unsigned long val, char *string);
void send_string(char *string);
void send_fixed(unsigned long val);
void send_int(unsigned long val);
void print_d(double x);

int main(void)
{
	//PGM_P p;
//	char buf[32];
	unsigned int timeval1;
	unsigned int timeval2;
	unsigned int timeval3;
	unsigned int timeval4;
	int flag = 1;

// Initialization
//	Leds_init();
	wdtdrv_disable();
	ACSR |= (1 << ACBG); // should be on for 70microS before init ADC
	DDRD = 0;
	MCUCR |= (1<<4);  // FIXME pull-up resistors disable
	PORTD = 0;	// FIXME also turn off pull-up resistors
	DDRB=0;	// Port B Inputs

	Usb_enable_regulator();
	start_boot_if_required();
	Clear_prescaler();
	DDRB=0;	// Port B Inputs
	usb_task_init();

	while (!Is_device_enumerated()) {
		usb_device_task();
	}
	timeval1 = sof_cnt;
	int tflag = 0;
// Redirect stdout to usb_putch for USB communication with printf
	FILE s=FDEV_SETUP_STREAM(putch,NULL,_FDEV_SETUP_WRITE);
	stdout=&s;
	
	while (1) {
		usb_device_task();	
		 if (sof_cnt - timeval1 > 500) {
			if (flag) {
				ADC_init();
				print_int(time_stuff, "UMaine ECE 498\n");
				printf("Version 1.0\n");
				flag = 0;
			}
			select_AIN_pin(tflag);
			double val1 = AC_conversion();
			double temp = (val1 - sensor_offset[tflag])/sensor_slope[tflag];

//			print_double(val1);
//			printf(" V\n");
//			val1=(45.806451)*val1 -23.964516129;
			if (tflag == 4) {
//				print_double(val1);
//				printf(" V\t");
				print_double(temp);
//				printf(" C\n");
				printf("\n");
//				printf(" V\t");
//				print_double(get_time_stuff());
//				printf("\n");
		//		printf("%d\n", tflag);
			} else if (tflag == 0) {
				set_time_stuff(get_global_var());
			} else {
//				print_double(val1);
//				printf(" V\t");
				print_double(temp);
//				printf(" C\t");
				printf("\t");
		//		printf("%d\t", tflag);
			}
			tflag++;
			if (tflag == 5) tflag = 0;
//			print_double(val1);
//			printf(" C\t");
			timeval1 = sof_cnt;

			/*select_AIN_pin(1);
			double val1 = AC_conversion();
			//print_int(val3,"% V\t");
			//print_int(Q_MULT((val3 - (QONE/2)), 100<<16), "% C\t");
			printf("%lf V\n",val1);
			printf("%lf C\n",(val1-0.5)*100);
			timeval1 = sof_cnt;
		*/} 
/*
		if (sof_cnt - timeval2 > 2000) {
			if (flag) {
				ADC_init();
				print_int(time_stuff, "UMaine ECE 498\n");
				flag = 0;
			}
			select_AIN_pin(2);
			double val2=AC_conversion();
	//		print_double(val2);
	//		printf(" V\n");
			printf("2\t");
//			val2=(45.806451)*val2 -23.964516129;
//			print_double(val2);
			printf(" C\t");
			timeval2 = sof_cnt;

			double val2 = AC_conversion();
			//print_int(val2,"% V\t");
			//print_int(Q_MULT((val2 - (QONE/2)), 100<<16), "% C\t");	
			printf("%lf V\n",val2);			
			printf("%lf C\n",(val2-0.5)*100);
			timeval2 = sof_cnt;
		} 
		if (sof_cnt - timeval3 > 2000) {
			if (flag) {
				ADC_init();
				print_int(time_stuff, "UMaine ECE 498\n");
				flag = 0;
			}
			select_AIN_pin(3);
			double val3=AC_conversion();
	//		print_double(val3);
	//		printf(" V\n");
			val3=(45.806451)*val3 -23.964516129;  
			printf("3\t");
//			print_double(val3);
//			printf(" C\t");
			timeval3 = sof_cnt;

			double val3 = AC_conversion();
			//print_int(val3,"% V\t");
			//print_int(Q_MULT((val3 - (QONE/2)), 100<<16), "% C\t");
			printf("%lf V\n",val3);
			printf("%lf C\n",(val3-0.5)*100);
			timeval3 = sof_cnt;
		} 
		if (sof_cnt - timeval4 > 2000) {		

			if (flag) {
				ADC_init();
				
				printf("UMAINE ECE 498\n");
				flag = 0;
			}		
			select_AIN_pin(4);
			
			double val4=AC_conversion();
	//		print_double(val4);
	//		printf(" V\n");
			val4=(45.806451)*val4 -23.964516129;
			printf("4\n");
//			print_double(val4);
//			printf(" C\n");
			timeval4 = sof_cnt;
			
		} 
*/	
	}

}

void print_int(unsigned long val, char *string)
{
	int i = 0;
	while ((string[i] != '\0') && (string[i] != '%')) i++;

	if (string[i] == '%') {
		string[i] = '\0';
		send_string(string);
		string[i] = '%';
		send_fixed(val);
		send_string(string + i + 1);
		i++;
		return;
	}
	string[i] = '\0';
	send_string(string);
}

void send_string(char *string)
{
	int i = 0;

	while (string[i] != '\0') {
		putch(string[i++]);
	}

	return;
}

void send_fixed(unsigned long val)
{
	unsigned long temp;
	send_int(val >> QDOT);

	temp = val & (QONE - 1);
	temp *= 1000;
	temp = temp / (QONE);

	putch('.');
	if (temp < 100) {
		if (temp < 10) {
			putch('0');
		}
		putch('0');
	}

	send_int(temp);
	return;
}

void print_d(double x){
/*	int y,z;
	z=(int)x;
	y=(int)(x*100)%100;
	printf("%d.",z);
	printf("%d",y);	
*/	 int c;
    	double fi;
	x=modf(x,&fi);
    	c=printf("%d.",(int)fi);
    	modf(x*1000,&fi);
    	c+=printf("%03d",(int)fi);
   	return c;

}



void send_int(unsigned long val)
{
    char ascii[17];
    char ct;
    ascii[16]='\0';
    for (ct=15;ct>=0;ct--)
    {
        ascii[(int)ct]=(val%10)+'0';
        val/=10;
        if (!val) break;
    }
    send_string(&ascii[(int)ct]);
    return;
}

//! \name Procedure to speed up the startup code
//! This one increment the CPU clock before RAM initialisation
//! @{
#ifdef  __GNUC__
// Locate low level init function before RAM init (init3 section)
// and remove std prologue/epilogue
char __low_level_init(void) __attribute__ ((section(".init3"), naked));
#endif

#ifdef __cplusplus
extern "C" {
#endif
	char __low_level_init() {
		Clear_prescaler();
		return 1;
	}
#ifdef __cplusplus
}
#endif
//! @}


